# Lucid is (C) Copyright 2006-2007 by Infiscape Corporation
#
# This file is part of Lucid, a PyOpenSG example application.
#
# Lucid is free software; you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# Lucid is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program.  If not, see <http://www.gnu.org/licenses/>.

from PyQt4 import QtGui, QtCore
import chunk_material_fceditor_base
import lucid.core
import osg2
from pydispatch import dispatcher
from lucid.util.qt.property_tree import *

import lucid.plugins.field_editors.field_editors as field_editors
import lucid.plugins.fc_editor.fc_editors as fc_editors


class ChunkMaterialEditorPlugin(lucid.core.IFcEditorPlugin):
   """ Custom editor for chunk material fc's. 
   
       This editor is needed because we have to edits multiple chunks
       as part of the chunk material.
   """
   def __init__(self):
      super(ChunkMaterialEditorPlugin, self).__init__()
      self.chunkMat = None
      self.widget = ChunkMaterialEditorWidget(self)
      self._selectedProp = None    # Most recently selected prop in tree
      self._selectedChunk = None   # Most recently selected chunk in tree
      
      mat_tree = self.widget.mMaterialTree
      self.mMaterialTreeModel = PropertyTreeModel(None)
      mat_tree.setModel(self.mMaterialTreeModel)
      
      # Context menus
      mat_tree.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
      mat_tree.connect(mat_tree,
                       QtCore.SIGNAL("customContextMenuRequested(QPoint)"),
                       self.onPropTreeContextMenuReq)
      mat_tree.connect(mat_tree.selectionModel(),
                       QtCore.SIGNAL("selectionChanged(QItemSelection,QItemSelection)"), 
                       self.onTreeSelected)      
      
      self.widget.connect(self.widget.mCreateChunkBtn, QtCore.SIGNAL("clicked(bool)"),
                          self.onAddChunk)
      self.widget.connect(self.widget.mDelChunkBtn, QtCore.SIGNAL("clicked(bool)"),
                          self.onDeleteChunk)


   @staticmethod
   def getName():
      return "Transform Core Editor"
      
   @staticmethod
   def getSupportedFcTypes():
      """ Return the type(s) that we support editing. """
      return [osg2.ChunkMaterial, ]
   
   def getEditorWidget(self):
      return self.widget

   def setFieldContainer(self, fc):
      assert type(fc) == osg2.ChunkMaterial      
      self.chunkMat = fc
      self._selectedProp = None
      self._selectedChunk = None      
      
      # Allocate the editor to use
      mat_tree = self.widget.mMaterialTree
      container = ChunkMaterialPropertyContainer(self.chunkMat)
      self.mMaterialTreeModel.setPropRoot(container)
      mat_tree.setRootIndex(self.mMaterialTreeModel.indexOf(self.mMaterialTreeModel.propRoot))
      mat_tree.resizeColumnToContents(0)
   
   
   def onPropTreeContextMenuReq(self, pos):
      print "Requested prop tree menu."
      cur_item = self._selectedProp
      cur_chunk = self._selectedChunk
      
      # Only have context menu for chunk case
      if cur_chunk:
         menu = QtGui.QMenu(None)
         create_menu = self.buildCreateChunkMenu()
         menu.addMenu(create_menu)
         menu.addSeparator()
         menu.addAction("Delete",self.onDeleteChunk)
         menu.exec_(QtGui.QCursor.pos())
         
   def onTreeSelected(self, selected, deselected):
      if len(selected.indexes()) > 0:
         index = selected.indexes()[0]
         selected_prop = self.mMaterialTreeModel.data(index,QtCore.Qt.UserRole)
         print "Selected prop: ", selected_prop

         # Update selected prop and selected chunk
         self._selectedProp = selected_prop
         self._selectedChunk = None
         if selected_prop and isinstance(self._selectedProp.mFC, osg2.StateChunk):
            self._selectedChunk = self._selectedProp.mFC
         print "Selected chunk: ", self._selectedChunk

   # ----------- Custom Chunk stuff --------- #
   # There is custom code for the case of editing a ChunkMaterial
   def onAddChunk(self):
      print "Add chunk"
      create_menu = self.buildCreateChunkMenu()
      create_menu.exec_(QtGui.QCursor.pos())
      
   def onDeleteChunk(self):
      " Delete the current selected chunk "
      # Remove the chunk and then update the property model      
      if self._selectedChunk:
         print "Removing chunk: [%s]:%s", (self._selectedChunk.getType().getCName(),self._selectedChunk)
         self.chunkMat.subChunk(self._selectedChunk)
         self._selectedChunk = None
         self.mMaterialTreeModel.propRoot.updateChunks()
         self.mMaterialTreeModel.reset()         
      else:
         print "No chunk selected to delete."

   def createChunk(self,chunkType):
      print "Adding chunk: ", chunkType
      new_chunk = chunkType.create()
      self.chunkMat.addChunk(new_chunk)
      self._selectedChunk = new_chunk
      self.mMaterialTreeModel.propRoot.updateChunks()
      self.mMaterialTreeModel.emit(QtCore.SIGNAL("layoutChanged()"))
      
   def buildCreateChunkMenu(self):
      """ Build up the menu of items that could be added. """
      chunk_types = [c for c in osg2.__dict__.itervalues() if isinstance(c,type) \
                                    and (osg2.StateChunk in c.__mro__) \
                                    and (not c.__name__.endswith("Base")) \
                                    and (hasattr(c,"create"))]
      self._chunk_create_calls = []
      create_menu = QtGui.QMenu("Create")
      for ct in chunk_types:
         create_call = lambda ctype=ct: self.createChunk(ctype)
         self._chunk_create_calls.append(create_call)
         create_menu.addAction(ct.__name__, create_call)
      return create_menu



class ChunkMaterialEditorWidget(QtGui.QWidget, chunk_material_fceditor_base.Ui_Form):
   """ Simple container widget. """
   def __init__(self, plugin, parent=None):
      QtGui.QWidget.__init__(self, parent)
      self.plugin = plugin
      self.setupUi()      
   
   def setupUi(self):
      " Local UI setup support. "
      chunk_material_fceditor_base.Ui_Form.setupUi(self,self)
      
      tree_parent = self.mFcdEditWidget.parent()
      self.mFcdEditWidget.setParent(None)
      self.mFcdEditWidget = None
      
      self.mMaterialTree = PropertyTreeView(tree_parent)
      tree_parent.layout().addWidget(self.mMaterialTree)
      

# ----------------- Chunk Material Properties ----------------------- #
class ChunkMaterialPropertyContainer(PropertyContainer):
   def __init__(self, chunkMaterial):
      super(ChunkMaterialPropertyContainer,self).__init__("Chunk Material")
      self.mChunkMaterial = chunkMaterial
      mat_name = osg2.getName(self.mChunkMaterial)
      if mat_name:
         self.name = mat_name
      self.updateChunks()

   
   def updateChunks(self):
      """ Update the contained chunks. """
      self.children = []
      cur_chunks = self.mChunkMaterial.getChunks()      
      for chunk in cur_chunks:
         group_type = fc_editors.getGroupPropertyEditorType(chunk)
         chunk_group = group_type(self, chunk)
         self.addChild(chunk_group)


#class ChunkPropertyGroup(PropertyGroup):
#   def __init__(self, parent, chunk):
#      super(ChunkPropertyGroup, self).__init__("", parent)
#      self.mChunk = chunk
#      self.updateName()
#      self.createProperties()
#      
#   def updateName(self):      
#      self.name = self.mChunk.getType().getCName()
#   
#   def createProperties(self):
#      field_editors.addGenericFCProperties(self, self.mChunk)      
